<template>
	<view class="">
		<view
			class="u-navbar"
			:style="[navbarStyle]"
			:class="{ 'u-navbar-fixed': isFixed, 'u-border-bottom': borderBottom }"
		>
			<view class="u-status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
			<view class="u-navbar-inner" :style="[navbarInnerStyle]">
				<view>
					<slot name="left">
						<view class="u-back-wrap" v-if="isBack" @tap="goBack">
							<view class="u-icon-wrap">
								<u-icon
									:name="backIconName"
									:color="backIconColor"
									:size="backIconSize"
								></u-icon>
							</view>
							<view
								class="u-icon-wrap u-back-text u-line-1"
								v-if="backText"
								:style="[backTextStyle]"
							>
								{{ backText }}
							</view>
						</view>
						<!-- 关闭原生返回 打开自定义返回 -->
						<view v-if="!isBack" class="slot-wrap">
							<!-- width: btnWidth + 'px', -->
							<view
								:class="isBlack ? 'backBlack' : 'back'"
								:style="{
									height: btnWidth > 0 ? dheight + 'px' : ''
								}"
							>
							<!-- 返回图标 --> 
							<image v-if="hasBackBtn && isBlack" 
								:show-loading="false" 
								@click="goBack" src="@/static/left.png"
								mode="" 
								style="width: 44rpx; height: 44rpx;"></image>
								<!-- 返回首页图标 -->
								<!-- <image style="width: 44rpx; height: 44rpx;":show-loading="false"
									v-if="hasHomeBtn && isBlack"
									@click="goHome"
									src="@/static/shouye.png"
									:style="{ marginLeft: hasBackBtn ? '40rpx' : '' }"
									mode=""></image> -->
								
							</view>
						</view>
					</slot>
				</view>
 
				<view class="u-navbar-content-title" v-if="title" :style="[titleStyle]">
					<view
						class="u-title u-line-1"
						:style="{
							color: titleColor,
							fontSize: titleSize + 'rpx',
							fontWeight: titleBold ? 'bold' : 'normal'
						}"
					>
						{{ title }}  
					</view>
				</view>
				<view class="u-slot-content"><slot></slot></view>
				<view class="u-slot-right"><slot name="right"></slot></view>
			</view>
		</view>
		<!-- 解决fixed定位后导航栏塌陷的问题 -->
		<view
			class="u-navbar-placeholder"
			v-if="isFixed && !immersive"
			:style="{ width: '100%', height: Number(navbarHeight) + statusBarHeight + 'px' }"
		></view>
	</view>
</template>
 
<script>
// 获取系统状态栏的高度
let systemInfo = uni.getSystemInfoSync();
export default {
	name: 'navbar',
	props: {
		// Tab页面组件的back
		TabPageBack: {
			type: Boolean | String,
			default: false
		},
		// 是否为黑色图标样式
		isBlack: {
			type: Boolean | String,
			default: true
		},
		// 默认是否显示自定义返回按钮
		backBtn: {
			type: Boolean | String,
			default: true
		},
		// 默认是否显示自定义主页按钮
		homeBtn: {
			type: Boolean | String,
			default: false
		},
		// 返回主页地址
		homeUrl: {
			type: String,
			default: '/pages/index/index'
		},
		// 上面是自定义的参数  下面是uView的参数---------------------------
		// uView的自带的返回 建议关闭 打开就没有自定义返回
		// 导航栏高度，单位px，非rpx
		height: {
			type: [String, Number],
			default: ''
		},
		// 返回箭头的颜色
		backIconColor: {
			type: String,
			default: '#606266'
		},
		// 左边返回的图标
		backIconName: {
			type: String,
			default: 'nav-back'
		},
		// 左边返回图标的大小，rpx
		backIconSize: {
			type: [String, Number],
			default: '44'
		},
		// 返回的文字提示
		backText: {
			type: String,
			default: ''
		},
		// 返回的文字的 样式
		backTextStyle: {
			type: Object,
			default() {
				return {
					color: '#606266'
				};
			}
		},
		// 导航栏标题
		title: {
			type: String,
			default: '设备录入'
		},
		// 标题的宽度，如果需要自定义右侧内容，且右侧内容很多时，可能需要减少这个宽度，单位rpx
		titleWidth: {
			type: [String, Number],
			default: '250'
		},
		// 标题的颜色
		titleColor: {
			type: String,
			default: '#606266'
		},
		// 标题字体是否加粗
		titleBold: {
			type: Boolean,
			default: false
		},
		// 标题的字体大小
		titleSize: {
			type: [String, Number],
			default: 34
		},
		// change by xxx uView自带的返回按钮  建议直接关闭先
		isBack: {
			type: [Boolean, String],
			default: false
		},
		// 对象形式，因为用户可能定义一个纯色，或者线性渐变的颜色
		background: {
			type: Object,
			default() {
				return {
					// background: 'linear-gradient(to right, #ff00ff, #00ff7f, #00ffff)'
					background: '#aaffff'
				};
			}
		},
		// 导航栏是否固定在顶部
		isFixed: {
			type: Boolean,
			default: true
		},
		// 是否沉浸式，允许fixed定位后导航栏塌陷，仅fixed定位下生效
		immersive: {
			type: Boolean,
			default: false
		},
		// 是否显示导航栏的下边框
		borderBottom: {
			type: Boolean,
			default: true
		},
		zIndex: {
			type: [String, Number],
			default: ''
		},
		// 自定义返回逻辑
		customBack: {
			type: Function,
			default: null
		}
	},
	data() {
		return {
			statusBarHeight: systemInfo.statusBarHeight,
			dwidth: 0,
			dheight: 0
		};
	},
	computed: {
		btnWidth() {
			var width =
				(this.hasBackBtn ? this.dwidth / 2 : 0) + (this.hasHomeBtn ? this.dwidth / 2 : 0);
			return width;
		},
		// 是否存在返回图标
		hasBackBtn() {
			return (this.backBtn && this.IsPageBack()) || this.TabPageBack;
		},
		// 判断是否存在回到首页按钮
		hasHomeBtn() {
			return (
				this.homeBtn ||
				this.homeUrl !== '/' + getCurrentPages()[getCurrentPages().length - 1].route
			);
		},
		menuButtonInfo() {
			// 如果是小程序，获取右上角胶囊的尺寸信息，避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API，尚未兼容)
			// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
			return uni.getMenuButtonBoundingClientRect();
			// #endif
 
			//#ifdef APP-PLUS
			return {
				bottom: 80,
				height: 32,
				left: 278,
				right: 365,
				top: 48,
				width: 87
			};
			//#endif
		},
		// 导航栏内部盒子的样式
		navbarInnerStyle() {
			let style = {};
			// 导航栏宽度，如果在小程序下，导航栏宽度为胶囊的左边到屏幕左边的距离
			style.height = this.navbarHeight + 'px';
			// // 如果是各家小程序，导航栏内部的宽度需要减少右边胶囊的宽度
			// #ifdef MP
			let rightButtonWidth = systemInfo.windowWidth - this.menuButtonInfo.left;
			style.marginRight = rightButtonWidth + 'px';
			// #endif
			return style;
		},
		// 整个导航栏的样式
		navbarStyle() {
			let style = {};
			style.zIndex = this.zIndex ? this.zIndex : 980;
			// 合并用户传递的背景色对象
			Object.assign(style, this.background);
			return style;
		},
		// 导航中间的标题的样式
		titleStyle() {
			let style = {};
			// #ifndef MP
			style.left = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
			style.right = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
			// #endif
			// #ifdef MP
			// 此处是为了让标题显示区域即使在小程序有右侧胶囊的情况下也能处于屏幕的中间，是通过绝对定位实现的
			let rightButtonWidth = systemInfo.windowWidth - this.menuButtonInfo.left;
			style.left = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
			style.right =
				rightButtonWidth -
				(systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 +
				rightButtonWidth +
				'px';
			// #endif
			style.width = uni.upx2px(this.titleWidth) + 'px';
			return style;
		},
		// 转换字符数值为真正的数值
		navbarHeight() {
			// #ifdef APP-PLUS || H5
			return this.height ? this.height : 44;
			// #endif
			// #ifdef MP
			// 小程序特别处理，让导航栏高度 = 胶囊高度 + 两倍胶囊顶部与状态栏底部的距离之差(相当于同时获得了导航栏底部与胶囊底部的距离)
			// 此方法有缺陷，暂不用(会导致少了几个px)，采用直接固定值的方式
			// return this.menuButtonInfo.height + (this.menuButtonInfo.top - this.statusBarHeight) * 2;//导航高度
			let height = systemInfo.platform == 'ios' ? 44 : 48;
			return this.height ? this.height : height;
			// #endif
		}
	},
	created() {
		this.dwidth =
			this.menuButtonInfo && this.menuButtonInfo.width ? this.menuButtonInfo.width : 88;
		this.dheight =
			this.menuButtonInfo && this.menuButtonInfo.height ? this.menuButtonInfo.height : 32;
	},
	methods: {
		rpx2px(val) {
			return uni.upx2px(val);
		},
		goBack() {
			// 如果自定义了点击返回按钮的函数，则执行，否则执行返回逻辑
			if (typeof this.customBack === 'function') {
				// 在微信，支付宝等环境(H5正常)，会导致父组件定义的customBack()函数体中的this变成子组件的this
				// 通过bind()方法，绑定父组件的this，让this.customBack()的this为父组件的上下文
				this.customBack.bind(this.$UniUtils.getParent.call(this))();
			} else {
				uni.navigateBack();
			}
		},
		goHome() {
			uni.switchTab({
				url: this.homeUrl,
				fail: e => {
					uni.navigateTo({
						url: this.homeUrl
					});
				},
				complete: res => {
					// console.log(res)
				}
			});
		},
		IsPageBack() {
			return getCurrentPages().length > 1;
		}
	}
};
</script>
 
<style scoped lang="scss">
// 定义混入指令，用于在非nvue环境下的flex定义，因为nvue没有display属性，会报错
@mixin vue-flex($direction: row) {
	// /* #ifndef APP-NVUE */
	display: flex;
	flex-direction: $direction;
	// /* #endif */
}
 
.u-border-bottom {
	position: relative;
}
 
.u-border-bottom:after {
	// /* #ifndef APP-NVUE */
	content: ' ';
	// /* #endif */
	position: absolute;
	left: 0;
	top: 0;
	pointer-events: none;
	box-sizing: border-box;
	-webkit-transform-origin: 0 0;
	transform-origin: 0 0;
	// 多加0.1%，能解决有时候边框缺失的问题
	width: 199.8%;
	height: 199.7%;
	transform: scale(0.5, 0.5);
	border: 0 solid #e4e7ed;
	z-index: 2;
	border-bottom-width: 1px;
}
 
/* start--icon图标外层套一个view，让其达到更好的垂直居中的效果--start */
.u-icon-wrap {
	display: flex;
	align-items: center;
}
 
/* start--文本行数限制--start */
.u-line-1 {
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
}
 
.u-navbar {
	width: 100%;
}
 
.u-navbar-fixed {
	position: fixed;
	left: 0;
	right: 0;
	top: 0;
	z-index: 991;
}
 
.u-status-bar {
	width: 100%;
}
 
.u-navbar-inner {
	@include vue-flex;
	justify-content: space-between;
	position: relative;
	align-items: center;
}
 
.u-back-wrap {
	@include vue-flex;
	align-items: center;
	flex: 1;
	flex-grow: 0;
	padding: 14rpx 14rpx 14rpx 24rpx;
}
 
.u-back-text {
	padding-left: 4rpx;
	font-size: 30rpx;
}
 
.u-navbar-content-title {
	@include vue-flex;
	align-items: center;
	justify-content: center;
	flex: 1;
	position: absolute;
	left: 0;
	right: 0;
	height: 60rpx;
	text-align: center;
	flex-shrink: 0;
}
 
.u-navbar-centent-slot {
	flex: 1;
}
 
.u-title {
	line-height: 60rpx;
	font-size: 32rpx;
	flex: 1;
}
 
.u-navbar-right {
	flex: 1;
	@include vue-flex;
	align-items: center;
	justify-content: flex-end;
}
 
.u-slot-content {
	flex: 1;
	@include vue-flex;
	align-items: center;
}
 
// add by xxx
.slot-wrap {
	display: flex;
	align-items: center;
	/* 如果您想让slot内容占满整个导航栏的宽度 */
	/* flex: 1; */
	/* 如果您想让slot内容与导航栏左右有空隙 */
	padding: 0 24rpx;
 
	.back {
		border-radius: 40rpx;
		display: flex;
		justify-content: space-between;
		align-items: center;
	}
 
	.backBlack {
		border-radius: 40rpx;
		display: flex;
		justify-content: space-between;
		align-items: center;
	}
}
</style>